﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using ibba.src.noriskbo.code;
using Infragistics.Documents.Excel;

namespace ibba.src.noriskbo.ViewModels
{

    public class ImportarGarantiasViewModel : Base.ViewModelImportacaoBase<ServiceGarantia.GarantiaManualImportacao>
    {
        private ServiceGarantia.IServiceGarantia _service;
        private LogAuditoria _msgLogAuditoria;

        public bool _erroNaValidacao;
        public bool _erroNaImportacao;

        //private Dictionary<int, string> _dicGarantidores;
        //private const string ERRO_GARANTIDOR = "ERRO_GARANTIDOR";

        private class GarantidorAux
        {
            public int Id { get; set; }
            public string Nome { get; set; }
            public string CnpjCpf { get; set; }
            public string TipoPessoa { get; set; }
            public bool Error { get; set; }
        }
        private List<GarantidorAux> _tableGarantidores;

        public ImportarGarantiasViewModel()
        {
            base.TitleView = "Importação de Garantias Manuais";

            _tableGarantidores = new List<GarantidorAux>();

            if (!base.IsInDesignMode)
            {
                _service = ServiceFactory.Instance.ServiceGarantia;
                base.DadosPlanilha = new ObservableCollection<ServiceGarantia.GarantiaManualImportacao>();

                DetalheGarantidores = new DetailsAux<ServiceGarantia.GarantidorManualLote>();

                DetalheGarantidores.OnChangeDetails += new DetailsAux<ServiceGarantia.GarantidorManualLote>.EventChangeDetails(DetalheGarantidores_OnChangeDetails);
                DetalheGarantidores.OnChangeFlagAcaoSQL += new DetailsAux<ServiceGarantia.GarantidorManualLote>.EventChangeFlagAcaoSQL(DetalheGarantidores_OnChangeFlagAcaoSQL);
            }
        }

        void DetalheGarantidores_OnChangeDetails()
        {
            if (RegistroSelecionado != null)
            {
                RegistroSelecionado.Garantidores = DetalheGarantidores.ListaOC.ToList();
            }
        }

        void DetalheGarantidores_OnChangeFlagAcaoSQL(object sender, Enums.TipoAcaoSQL oldType, Enums.TipoAcaoSQL newType)
        {
            if (sender != null)
            {
                //Se foi alterado retira o flag de Erro e disparando atualização da imagem de flag
                ((ServiceGarantia.GarantidorManualLote)sender).Error = false;
            }
        }

        public void Clear()
        {
            //_tableGarantidores.Clear();
            DadosPlanilha.Clear();
            DetalheGarantidores.ListaOC.Clear();

            base.PlanilhaExcel = null;
            base.ExcelFileName = string.Empty;

            this.NotifyProperties();
        }

        private ServiceGarantia.GarantiaManualImportacao _registroSelecionado;
        public ServiceGarantia.GarantiaManualImportacao RegistroSelecionado
        {
            get { return _registroSelecionado; }
            set
            {
                //Sempre que navegar entre os registros de garantia irá salvar a lista
                //if (_registroSelecionado != null && _registroSelecionado != value)
                //    _registroSelecionado.Garantidores = DetalheGarantidores.ListaOC.ToList();

                if (base.SetValue("RegistroSelecionado", ref _registroSelecionado, value))
                {
                    AtualizarListaGarantidores();
                    base.RaisePropertyChanged("HabilitarInclusaoGarantidor");
                }
            }
        }

        private void AtualizarListaGarantidores()
        {
            if (RegistroSelecionado != null && RegistroSelecionado.Garantidores != null)
                DetalheGarantidores.CarregarDetalhes(RegistroSelecionado.Garantidores.OrderBy(o => o.Nome).ToList(), false);
            else
                DetalheGarantidores.ListaOC.Clear();
        }

        private DetailsAux<ServiceGarantia.GarantidorManualLote> _detalheGarantidores;
        public DetailsAux<ServiceGarantia.GarantidorManualLote> DetalheGarantidores
        {
            get { return _detalheGarantidores; }
            set { base.SetValue("DetalheGarantidores", ref _detalheGarantidores, value); }
        }

        public bool HabilitarInclusaoGarantidor
        {
            get
            {
                //return RegistroSelecionado != null 
                //    && (RegistroSelecionado.StatusImportacao == Constantes.StatusImportLote.ALTERACAO || 
                //        RegistroSelecionado.StatusImportacao == Constantes.StatusImportLote.COPIAR ||
                //        RegistroSelecionado.StatusImportacao == Constantes.StatusImportLote.INCLUSAO);

                return RegistroSelecionado != null;
            }
        }


        #region [ Comandos de Botões ]

        protected override void CarregarDados(Worksheet pSheet)
        {
            int lin = 0;
            int col = 0;
            int colNull = 0;

            FileStream stream = null;

            try
            {
                base.StartBusy();

                DadosPlanilha.Clear();

                foreach (var r in pSheet.Rows)
                {
                    lin = r.Index;

                    if ((lin > 1) && (r.Cells[0] != null))
                    {
                        col = 0;
                        colNull = 0;

                        var item = new ServiceGarantia.GarantiaManualImportacao();

                        item.CodigoContrato = string.Empty;
                        item.CodigoProduto = string.Empty;
                        item.CodigoModalidade = string.Empty;
                        item.CodigoMoeda = string.Empty;

                        //item.DataVencimento = DateTime.Now;

                        foreach (WorksheetCell cell in r.Cells)
                        {
                            SetValue(item, cell);

                            if (cell.Value == null)
                                colNull++;

                            ////Por padrão a leitura da coleção não efetua leitura de celulas nula
                            //if ((_col - cell.ColumnIndex) < 0)
                            //{
                            //    item.DescricaoErro = string.Format("Valor incorreto na celula {0}{1} da planilha.", Convert.ToChar(_col + 65), _lin);
                            //    item.StatusImportacao = Constantes.StatusImportLote.ERRO;
                            //}

                            col = cell.ColumnIndex;
                        }

                        if (colNull != r.Cells.Count())
                        {
                            if (item.CodigoContrato.Length > 20)
                                item.CodigoContrato = item.CodigoContrato.Substring(0, 20);

                            if (item.CodigoProduto.Length > 15)
                                item.CodigoProduto = item.CodigoProduto.Substring(0, 15);

                            if (item.CodigoModalidade.Length > 15)
                                item.CodigoModalidade = item.CodigoModalidade.Substring(0, 15);

                            if (item.CodigoMoeda.Length > 3)
                                item.CodigoMoeda = item.CodigoMoeda.Substring(0, 3);

                            item.Garantidores = new List<ServiceGarantia.GarantidorManualLote>();
                            DadosPlanilha.Add(item);
                        }
                    }

                }

                CarregarPlanilhaGarantidor();

            }
            catch (Exception ex)
            {
                if (lin > 0)
                    MessageBoxHelper.ShowErro(AppHelper.NomeSistema, string.Format("Ocorreu um erro na linha {0}, coluna {1}", lin + 1, col + 1), ex.Message.ToString());
                else
                    MessageBoxHelper.ShowErro(AppHelper.NomeSistema, "Não foi possível carregar o arquivo", ex.Message.ToString());
            }
            finally
            {
                if (stream != null)
                    stream.Close();

                base.NotifyProperties();
                base.EndBusy("Carregando...");
            }

        }

        /// <summary>
        /// Carrega dados da planilha de garantidores
        /// </summary>
        private void CarregarPlanilhaGarantidor()
        {
            ServiceGarantia.GarantiaManualImportacao ga;
            ServiceGarantia.GarantidorManualLote gd;
            ServiceGarantia.GarantidorManualLote itemGd;

            var sheetGd = this.GetWorksheet(1); //planilha garantidor

            if (sheetGd != null)
            {
                foreach (var row in sheetGd.Rows)
                {
                    if ((row.Index > 1) && (row.Cells[0] != null))
                    {
                        ga = new ServiceGarantia.GarantiaManualImportacao();
                        gd = new ServiceGarantia.GarantidorManualLote();

                        //Lendo informações da planilha
                        foreach (WorksheetCell cell in row.Cells)
                        {
                            try
                            {
                                var value = cell.Value;

                                switch (cell.ColumnIndex)
                                {
                                    case 0: ga.Numero = Convert.ToInt32(value);
                                        break;
                                    case 1: ga.CodigoContrato = Convert.ToString(value);
                                        break;
                                    case 2: ga.CodigoProduto = Convert.ToString(value);
                                        break;
                                    case 3: ga.CodigoModalidade = Convert.ToString(value);
                                        break;
                                    case 4: ga.IdCliente = Convert.ToInt32(value);
                                        break;
                                    case 5: gd.IdPessoa = Convert.ToInt32(value);
                                        break;
                                    case 6: gd.PercentualGarantidor = Convert.ToDecimal(value);
                                        if (gd.PercentualGarantidor > 100)
                                            gd.PercentualGarantidor = 100;
                                        break;
                                    case 7: gd.FlagAcaoSQL = Convert.ToBoolean(value)
                                                             ? ServiceGarantia.enumAcaoSQL.Delete
                                                             : ServiceGarantia.enumAcaoSQL.None;
                                        break;
                                    default:
                                        break;
                                }

                            }
                            catch (Exception ex)
                            {
                                ga.DescricaoErro += "Erro de preenchimento das informações na planilha de garantidores." + Environment.NewLine;
                                ga.StatusImportacao = Constantes.StatusImportLote.ERRO; 
                                //MessageBoxHelper.ShowErro(AppHelper.NomeSistema, "Não foi possível carregar a planilha de garantidores", ex.Message.ToString());
                                //return;
                            }

                        }

                        //Verifica se a garantia da planilha garantidores já foi carregada pela planilha de garantias
                        if (!(string.IsNullOrWhiteSpace(ga.CodigoContrato) ||
                              string.IsNullOrWhiteSpace(ga.CodigoProduto) ||
                              string.IsNullOrWhiteSpace(ga.CodigoModalidade)))
                        {
                            //Verifica a existencia da garantia
                            var listGarantia = DadosPlanilha.Where(a => a.CodigoContrato.Trim().ToUpper() == ga.CodigoContrato.Trim().ToUpper()
                                                                     && a.CodigoProduto.Trim().ToUpper() == ga.CodigoProduto.Trim().ToUpper()
                                                                     && a.CodigoModalidade.Trim().ToUpper() == ga.CodigoModalidade.Trim().ToUpper()
                                                                     && a.IdCliente == ga.IdCliente
                                                                     && a.Numero == ga.Numero).ToList();

                            //Se encontrou a garantia
                            if (listGarantia != null && listGarantia.Count > 0)
                            {
                                //adiciona o garantidor à garantia existente
                                foreach (var itemGa in listGarantia)
                                {
                                    itemGd = null;

                                    //Verifica se o garantidor da planilha já está na lista da garantia selecionada
                                    if (itemGa.Garantidores.Count > 0)
                                        itemGd = itemGa.Garantidores.SingleOrDefault(a => a.IdPessoa == gd.IdPessoa);

                                    if (itemGd != null)
                                    {
                                        itemGd.PercentualGarantidor = gd.PercentualGarantidor;
                                        itemGd.FlagAcaoSQL = gd.FlagAcaoSQL;
                                    }
                                    else
                                    {
                                        gd.IdGarantia = itemGa.IdGarantia;
                                        itemGa.Garantidores.Add(gd); //adiciona o garantidor na lista da garantia selecionada                                        
                                    }
                                }
                            }
                            else
                            {
                                //Se não encontrou garantia insere uma nova para adicionar o garantidor
                                if (gd.FlagAcaoSQL != ServiceGarantia.enumAcaoSQL.Delete)
                                    gd.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Insert;

                                ga.Garantidores = new List<ServiceGarantia.GarantidorManualLote>();
                                ga.Garantidores.Add(gd);

                                DadosPlanilha.Add(ga);
                            }
                        }

                    }

                }
            }
        }

        public override void ComandoValidarDados()
        {
            InvokeValidarDadosDeImportacao();            
        }

        public override void ComandoImportarDados()
        {
            int count = 0;
            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            sb.AppendLine("ATENÇÃO: Você está solicitando:");

            count = this.InsertCount;
            if (count > 0)
                sb.AppendLine(String.Format("\nInclusão de Rascunho:\n\t > {0} {1}", count, count == 1 ? "garantia" : "garantias"));


            count = this.UpdateCount;
            if (count > 0)
                sb.AppendLine(String.Format("\nAlteração de Rascunho:\n\t > {0} {1}", count, count == 1 ? "garantia" : "garantias"));


            count = this.CopyCount;
            if (count > 0)
                sb.AppendLine(String.Format("\nCopia de Aprovado ou Automático:\n\t > {0} {1}", count, count == 1 ? "garantia" : "garantias"));


            _msgLogAuditoria = new LogAuditoria();
            _msgLogAuditoria.Mensagem = sb.ToString();

            MessageBoxHelper.ShowQuestion("Importação de Garantias em Lote"
                        , sb.ToString()
                        , sl.componentes.CustomDialogEnums.enumCustomDialogIcons.Stop
                        , new sl.componentes.CustomDialog.DialogClosed((r) =>
                        {
                            //Atualiza a lista de garantidores da garantia selecionada
                            //RegistroSelecionado.Garantidores = DetalheGarantidores.ListaOC.ToList();

                            if (r == MessageBoxResult.Yes)
                                SalvarDadosDeImportacao();
                            else
                                _msgLogAuditoria = null;
                        }));
        }

        protected override void ValidarRetornoDados(ServiceGarantia.GarantiaManualImportacao pEntidade)
        {
            ServiceGarantia.GarantiaManualImportacao dado;
            List<ServiceGarantia.GarantiaManualImportacao> dados;

            dados = DadosPlanilha.Where(a => a.CodigoContrato.Trim() == pEntidade.CodigoContrato.Trim()
                                          && a.CodigoProduto.Trim() == pEntidade.CodigoProduto.Trim()
                                          && a.CodigoModalidade.Trim() == pEntidade.CodigoModalidade.Trim()
                                          && a.IdCliente == pEntidade.IdCliente
                                          && a.Numero == pEntidade.Numero).ToList();

            for (int i = 0; i < dados.Count; i++)
            {
                if (i == 0)
                {
                    dado = dados[0];


                    #region [ Atualizar dados da garantia ]
                    //Atualiza dados do retorno
                    //GeneralHelper.SincProperties(pEntidade, dado);                    
                    dado.IdGarantia = pEntidade.IdGarantia;
                    dado.IdProdutoRisco = pEntidade.IdProdutoRisco;
                    dado.NomeCliente = pEntidade.NomeCliente;
                    dado.IdCliente = pEntidade.IdCliente;
                    dado.CodigoInstrumento = pEntidade.CodigoInstrumento;
                    dado.Instrumento = pEntidade.Instrumento;
                    dado.CodigoBem = pEntidade.CodigoBem;
                    dado.Bem = pEntidade.Bem;
                    dado.CodigoNatureza = pEntidade.CodigoNatureza;
                    dado.Natureza = pEntidade.Natureza;                    
                    dado.CodigoMoeda = pEntidade.CodigoMoeda;
                    dado.CodigoStatus = pEntidade.CodigoStatus;

                    if (string.IsNullOrWhiteSpace(dado.Descricao))
                        dado.Descricao = pEntidade.Descricao;

                    if (dado.ValorAtualizado == -1)
                        dado.ValorAtualizado = pEntidade.ValorAtualizado;

                    if (dado.ValorOriginal == -1)
                        dado.ValorOriginal = pEntidade.ValorOriginal;


                    dado.DescricaoErro = string.Empty;

                    //Validação das informações
                    if (dado.IdGarantia == -1)
                    {
                        dado.DescricaoErro = "Ocorreu um erro com a importação deste registro!";
                    }
                    if (dado.IdGarantia > 0 && dado.CodigoStatus == Constantes.StatusFluxoLM.BAIXA_OPERACIONAL)
                    {
                        dado.DescricaoErro += "Existe uma BAIXA OPERACIONAL para este contrato\n";
                    }
                    if (dado.IdProdutoRisco == 0)
                    {
                        dado.DescricaoErro += "Codigo do Produto/Modalidade não encontrado!\n";
                    }
                    if (string.IsNullOrWhiteSpace(dado.NomeCliente))
                    {
                        dado.DescricaoErro += "Cliente não encontrado!\n";
                    }
                    if (string.IsNullOrWhiteSpace(dado.CodigoMoeda))
                    {
                        dado.DescricaoErro += "Codigo da Moeda não encontrada!\n";
                    }
                    //if (dado.IdGarantia == 0 && dado.CodigoInstrumento <= 0)
                    //{
                    //    dado.DescricaoErro += "Para inclusões é necessário informar a trinca da garantia!\n";
                    //}                    
                    if (dado.CodigoInstrumento == 0)
                    {
                        dado.DescricaoErro += "Trinca da Garantia não encontrada!\n";
                    }
                    if (dado.IdGarantia == 0 && string.IsNullOrWhiteSpace(dado.Descricao))
                    {
                        dado.DescricaoErro += "Para inclusões a descrição da garantia é obrigatória!\n";
                    }

                    #endregion

                    #region [ Atualização Lista Garantidores ]

                    ////Se registro selecionado for igual à garantia que está sendo validada.
                    //if (RegistroSelecionado != null && RegistroSelecionado.IdGarantia == pEntidade.IdGarantia)
                    //{
                    //    dado.Garantidores = DetalheGarantidores.ListaOC.ToList();
                    //    bUpdateDetalhe = true;
                    //}

                    if (dado.Garantidores.Count == 0)
                    {
                        //Carrega lista com o que vem da base
                        dado.Garantidores = pEntidade.Garantidores;
                    }
                    else
                    {
                        //Remove todos os garantidores cadastrados no caso de ter alterado o id da garantia
                        dado.Garantidores.RemoveAll(delegate(ServiceGarantia.GarantidorManualLote p)
                        {
                            return p.IdGarantidor > 0 && (p.IdGarantia > 0 && p.IdGarantia != pEntidade.IdGarantia);
                        });

                        foreach (var item in pEntidade.Garantidores)
                        {
                            //Atualiza garantidores que foram adicionados via planilha
                            var g = dado.Garantidores.SingleOrDefault(a => a.IdPessoa == item.IdPessoa);

                            if (g != null)
                            {
                                //Se encontrar preencher os valores de Id, Nome do Garantidor e Flag para Atualização
                                g.IdGarantia = item.IdGarantia;
                                g.IdGarantidor = item.IdGarantidor;
                                g.Nome = item.Nome;
                                g.CpfCnpj = item.CpfCnpj;
                                g.TipoPessoa = item.TipoPessoa;

                                if (g.FlagAcaoSQL != ServiceGarantia.enumAcaoSQL.Delete)
                                {
                                    if (g.PercentualGarantidor != item.PercentualGarantidor)
                                        g.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Update;
                                    else
                                        g.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.None;
                                }
                            }
                            else
                            {
                                dado.Garantidores.Add(item); //Adiciona garantidor na lista de garantidores
                            }
                        }


                        //Remove itens sem ID marcados para exclusão
                        //dado.Garantidores.Where(w => w.IdGarantidor == 0 
                        //                          && w.FlagAcaoSQL == ServiceGarantia.enumAcaoSQL.Delete).ToList()
                        //                 .ForEach(f => dado.Garantidores.Remove(f));

                        dado.Garantidores.RemoveAll(delegate(ServiceGarantia.GarantidorManualLote p)
                        {
                            return p.IdGarantidor == 0 && p.FlagAcaoSQL == ServiceGarantia.enumAcaoSQL.Delete;
                        });

                        //adicionar Id do Garantidor ao dicionario para posterior verificação
                        dado.Garantidores.Where(w => w.IdGarantidor == 0).ToList()
                                         .ForEach(f =>
                                         {
                                             f.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Insert;
                                             if (string.IsNullOrWhiteSpace(f.Nome))
                                                 AddDicionarioGarantidor(f.IdPessoa);
                                         });

                        //for (int idx = 0; idx < dado.Garantidores.Count; idx++)
                        //{
                        //    var item = dado.Garantidores[idx];

                        //    if (item.IdGarantidor == 0)
                        //    {
                        //        if (item.FlagAcaoSQL == ServiceGarantia.enumAcaoSQL.Delete)
                        //            dado.Garantidores.Remove(item);
                        //        else
                        //        {
                        //            item.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Insert;

                        //            if (string.IsNullOrWhiteSpace(item.Nome))
                        //                AddDicionarioGarantidor(item.IdPessoa); //adicionar Id do Garantidor ao dicionario para posterior verificação
                        //        }
                        //    }
                        //}

                    }

                    //if (bUpdateDetalhe)
                    //    DetalheGarantidores.CarregarDetalhes(dado.Garantidores, false);

                    #endregion

                }
                else
                {
                    //Se retornou mais de uma registro na consulta marca como duplicado
                    dado = dados[i];
                    dado.DescricaoErro = "Registro duplicado na planilha!";
                }


                //Marca status da validação
                if (string.IsNullOrEmpty(dado.DescricaoErro) == false)
                    dado.StatusImportacao = Constantes.StatusImportLote.ERRO;
                else
                    if (dado.IdGarantia == 0)
                    {
                        dado.StatusImportacao = Constantes.StatusImportLote.INCLUSAO;
                    }
                    else
                    {
                        if (dado.CodigoStatus == Constantes.StatusFluxoLM.RASCUNHO
                            || dado.CodigoStatus == Constantes.StatusFluxoLM.EM_APROVACAO
                            || string.IsNullOrEmpty(dado.CodigoStatus))
                            dado.StatusImportacao = base.IsImporting ? Constantes.StatusImportLote.FINALIZADO : Constantes.StatusImportLote.ALTERACAO;
                        else
                            dado.StatusImportacao = base.IsImporting ? Constantes.StatusImportLote.FINALIZADO : Constantes.StatusImportLote.COPIAR;
                    }

            }
        }
        
        #endregion //Comandos Botoes

        #region [ Métodos adicionais ] 

        /// <summary>
        /// Preenche e trata os valores da planilha excell
        /// </summary>
        /// <param name="pEntidade"></param>
        /// <param name="pCell"></param>
        private void SetValue(ServiceGarantia.GarantiaManualImportacao pEntidade, WorksheetCell pCell)
        {
            try
            {
                var value = pCell.Value;
                DateTime dtAux;

                switch (pCell.ColumnIndex)
                {
                    case 0: pEntidade.Numero = Convert.ToInt32(value);
                        break;
                    case 1: pEntidade.CodigoContrato = Convert.ToString(value);
                        break;
                    case 2: pEntidade.CodigoProduto = Convert.ToString(value);
                        break;
                    case 3: pEntidade.CodigoModalidade = Convert.ToString(value);
                        break;
                    case 4: pEntidade.IdCliente = Convert.ToInt32(value);
                        break;
                    case 5: pEntidade.Instrumento = Convert.ToString(value);
                        break;
                    case 6: pEntidade.Bem = Convert.ToString(value);
                        break;
                    case 7: pEntidade.Natureza = Convert.ToString(value);
                        break;
                    case 8: pEntidade.CodigoMoeda = value.ToString();
                        break;
                    case 9: pEntidade.ValorOriginal = Convert.ToDecimal(value);
                        break;
                    case 10: pEntidade.ValorAtualizado = Convert.ToDecimal(value);
                        break;
                    case 11: pEntidade.Descricao = Convert.ToString(value);
                        break;
                    case 12:
                        if (DateTime.TryParse(value.ToString(), out dtAux))
                            pEntidade.DataVencimento = dtAux;
                        else
                            pEntidade.DataVencimento = DateTime.FromOADate(Convert.ToDouble(value));

                        break;
                    case 13: pEntidade.Formalizada = Convert.ToBoolean(value);
                        break;
                    case 14: pEntidade.SobrepoeAutomatica = Convert.ToBoolean(value);
                        break;
                    default:
                        break;
                }

            }
            catch (Exception)
            {
                pEntidade.DescricaoErro = string.Format("Valor incorreto na celula {0}{1} da planilha.", Convert.ToChar(pCell.ColumnIndex + 65), pCell.RowIndex + 1);
                pEntidade.StatusImportacao = Constantes.StatusImportLote.ERRO;

                return;
            }
        }

        #region [ Manipulação de Garantidores ] 
        
        /// <summary>
        /// Adiciona Ids de Clientes para validação dos clientes inseridos via planilha
        /// </summary>
        /// <param name="pIdPessoa"></param>
        private void AddDicionarioGarantidor(int pIdPessoa)
        {
            var item = _tableGarantidores.SingleOrDefault(r => r.Id == pIdPessoa);

            if (item == null)
                _tableGarantidores.Add(new GarantidorAux { Id = pIdPessoa });

        }

        private void UpdateDicionarioGarantidor()
        {

            if (_tableGarantidores == null)
                return;

            foreach (var item in _tableGarantidores)
            {
                base.StartBusy();

                //Se ainda não foi verificado
                if (string.IsNullOrWhiteSpace(item.Nome))
                {
                    item.Error = true;

                    ServiceFactory.Instance.ServiceCorporativo.BeginObterCliente(item.Id,
                    pAsyncResult =>
                    {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate()
                        {
                            try
                            {
                                var result = ((ServiceCorporativo.ICorporativo)pAsyncResult.AsyncState).EndObterCliente(pAsyncResult);

                                if (result != null)
                                {
                                    _tableGarantidores.Where(w => w.Id == result.IdCliente && string.IsNullOrWhiteSpace(w.Nome)).ToList()
                                        .ForEach(f =>
                                        {
                                            f.Nome = string.Format("{0}", result.NomeCliente);
                                            f.CnpjCpf = string.Format("{0}", result.CnpjCpf);
                                            f.TipoPessoa = string.Format("{0}", result.TipoPessoa);
                                            f.Error = false;
                                        });
                                }

                            }
                            finally
                            {
                                base.EndBusy();

                                if (!base.IsBusy)
                                    UpdateNomesGarantidores(); //Se não está mais processando então varre todas as garantias para preencher o garantidor

                            }
                        });

                    }, ServiceFactory.Instance.ServiceCorporativo);
                }
                else
                {
                    UpdateNomesGarantidores(item);
                    base.EndBusy();
                }
            }

        }
        
        /// <summary>
        /// Atualizar os registros de garantidos dentro da lista de garantias
        /// </summary>
        private void UpdateNomesGarantidores()
        {
            if (_tableGarantidores == null)
                return;

            foreach (var item in _tableGarantidores)
            {
                UpdateNomesGarantidores(item);
            }

        }

        /// <summary>
        /// Atualizar os registros de garantidos dentro da lista de garantias
        /// </summary>
        private void UpdateNomesGarantidores(GarantidorAux item) // (KeyValuePair<int, string> item)
        {
            //Se já processou todos os itens do dicionario então 

            //bool bErro = (item.Value == ERRO_GARANTIDOR);

            //atualiza os garantidores da lista de persistencia
            foreach (var ga in DadosPlanilha)
            {
                ga.Garantidores.Where(w => w.IdPessoa == item.Id && string.IsNullOrWhiteSpace(w.Nome)).ToList()
                    .ForEach(f =>
                    {
                        f.Error = item.Error;
                        f.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Insert;

                        if (f.Error)
                        {
                            //Se garantidor com erro então marca com erro também
                            ga.CodigoStatus = Constantes.StatusImportLote.ERRO;
                            ga.DescricaoErro = "Garantidor não encontrado! Adicione o garantidor manualmente.";
                        }
                        else
                        {
                            f.Nome = item.Nome;
                            f.CpfCnpj = item.CnpjCpf;
                            f.TipoPessoa = item.TipoPessoa;
                        }
                    });
            }


            //Atualizar o registro dos detalhes selecionado
            if (DetalheGarantidores.ListaOC.Count > 0)
            {

                DetalheGarantidores.ListaOC.Where(w => w.IdPessoa == item.Id && string.IsNullOrWhiteSpace(w.Nome)).ToList().ForEach(f =>
                {
                    f.Error = item.Error;
                    f.FlagAcaoSQL = ServiceGarantia.enumAcaoSQL.Insert;

                    if (!f.Error)
                    {
                        f.Nome = item.Nome;
                        f.CpfCnpj = item.CnpjCpf;
                        f.TipoPessoa = item.TipoPessoa;
                    }
                });
            }

        }
                        
        internal void AddNovoGarantidor(int pIdPessoa, string pNomePessoa, string pCnpjCpf, char pTipoPessoa, decimal pPercGarantido)
        {
            ServiceGarantia.GarantidorManualLote garantidor = null;
            bool bnovo = false;

            if (this.HabilitarInclusaoGarantidor)
            {

                garantidor = DetalheGarantidores.ListaOC.SingleOrDefault(a => a.IdPessoa == pIdPessoa);

                if (garantidor == null)
                {
                    garantidor = new ServiceGarantia.GarantidorManualLote();
                    bnovo = true;
                }

                garantidor.IdPessoa = pIdPessoa;
                garantidor.Nome = pNomePessoa;
                garantidor.CpfCnpj = pCnpjCpf;
                garantidor.TipoPessoa = pTipoPessoa.ToString();
                garantidor.PercentualGarantidor = pPercGarantido;

                garantidor.FlagAcaoSQL = garantidor.IdGarantidor > 0 ? ServiceGarantia.enumAcaoSQL.Update : ServiceGarantia.enumAcaoSQL.Insert;
                garantidor.Error = false;

                if (bnovo)
                {
                    DetalheGarantidores.ListaOC.Add(garantidor);
                }

                RegistroSelecionado.Garantidores = DetalheGarantidores.ListaOC.ToList();
            }
        }

        internal void RemoverGarantidor(ServiceGarantia.GarantidorManualLote pGarantidor)
        {
            DetalheGarantidores.ListaOC.Remove(pGarantidor);
            RegistroSelecionado.Garantidores = DetalheGarantidores.ListaOC.ToList();
        }

        #endregion //manipulação de garantidores

        #region [ Validação dos dados ]

        private void InvokeValidarDadosDeImportacao()
        {
            base.BusyText = "Validando...";
            base.StartBusy();

            base.IsValidating = true;

            var contratos = GetDadosParaValidar(10);

            if (contratos.Count > 0)
            {
                _service.BeginValidarDadosDeImportacao(contratos,
                    (pAsyncResult) =>
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            try
                            {
                                InvokeValidarDadosDeImportacao();

                                var retorno = ((ServiceGarantia.IServiceGarantia)pAsyncResult.AsyncState).EndValidarDadosDeImportacao(pAsyncResult);

                                if (retorno != null && retorno.Count > 0)
                                {
                                    foreach (var ret in retorno)
                                        this.ValidarRetornoDados(ret);

                                }

                            }
                            catch (Exception)
                            {
                                _erroNaValidacao = true;
                            }
                            finally
                            {
                                base.NotifyProperties();
                                base.EndBusy("Carregando...");

                                if (!base.IsBusy)
                                {
                                    //Se não estiver mais processando e ocorreu erro na validação 
                                    //deve retirar o status de processando
                                    if (_erroNaValidacao)
                                    {
                                        _erroNaValidacao = false;
                                        DadosPlanilha.Where(w => w.StatusImportacao == Constantes.StatusImportLote.PROCESSANDO).ToList().ForEach(r => r.StatusImportacao = "");
                                    }

                                    UpdateDicionarioGarantidor();
                                }
                            }

                        });
                    }, _service);
            }
            else
            {
                base.IsValidating = false;

                base.NotifyProperties();
                base.EndBusy("Carregando...");
            }

        }

        private List<ServiceGarantia.ValidarImportacaoGarantia> GetDadosParaValidar(int pQtdItens)
        {
            var retorno = new List<ServiceGarantia.ValidarImportacaoGarantia>();
            int dup = 0;

            foreach (var item in DadosPlanilha)
            {
                if (string.IsNullOrEmpty(item.StatusImportacao))
                {
                    if (string.IsNullOrEmpty(item.CodigoContrato)
                        || string.IsNullOrEmpty(item.CodigoProduto)
                        || string.IsNullOrEmpty(item.CodigoModalidade)
                        || item.IdCliente <= 0
                        || item.Numero < 0)
                    {
                        item.DescricaoErro = "Campos chave são de preenchimento obrigatório";
                        item.StatusImportacao = Constantes.StatusImportLote.ERRO;
                    }
                    //else if (item.DataVencimento <= new DateTime(1900, 1, 1))
                    //{
                    //    item.DescricaoErro = "Data de Vencimento inválida";
                    //    item.StatusImportacao = Constantes.StatusImportLote.ERRO;
                    //}
                    //else if (string.IsNullOrWhiteSpace(item.CodigoMoeda))
                    //{
                    //    item.DescricaoErro = "Campo Moeda é de preenchimento obrigatório";
                    //    item.StatusImportacao = Constantes.StatusImportLote.ERRO;
                    //}
                    else //if (string.IsNullOrEmpty(item.StatusImportacao))
                    {
                        //Verifico se item já foi adicionado para validação
                        dup = retorno.Count(a => a.CodigoContrato.Trim() == item.CodigoContrato.Trim()
                                                 && a.CodigoProduto.Trim() == item.CodigoProduto.Trim()
                                                 && a.CodigoModalidade.Trim() == item.CodigoModalidade.Trim()
                                                 && a.IdCliente == item.IdCliente
                                                 && a.Numero == item.Numero);

                        if (dup > 0)
                        {
                            item.DescricaoErro = "Registro duplicado na planilha";
                            item.StatusImportacao = Constantes.StatusImportLote.ERRO;
                        }
                        else
                        {
                            item.StatusImportacao = Constantes.StatusImportLote.PROCESSANDO; //Sera validado

                            //Garantindo o tamanho das informações de campos string
                            if (item.CodigoContrato != null && item.CodigoContrato.Length > 20)
                                item.CodigoContrato = item.CodigoContrato.Substring(0, 20);

                            if (item.CodigoProduto != null && item.CodigoProduto.Length > 15)
                                item.CodigoProduto = item.CodigoProduto.Substring(0, 15);

                            if (item.CodigoModalidade != null && item.CodigoModalidade.Length > 15)
                                item.CodigoModalidade = item.CodigoModalidade.Substring(0, 15);

                            if (item.CodigoMoeda != null && item.CodigoMoeda.Length > 3)
                                item.CodigoMoeda = item.CodigoMoeda.Substring(0, 3);

                            retorno.Add(GeneralHelper.SincProperties(item, new ServiceGarantia.ValidarImportacaoGarantia()));

                            if ((pQtdItens > 0) && (retorno.Count >= pQtdItens))
                                break;

                        }
                    }
                }
            }

            return retorno;
        }
        
        #endregion //Validacao dos dados

        #region [ Importação dos dados ]
        
        private void SalvarDadosDeImportacao()
        {
            int count = DadosPlanilha.Count(x => x.StatusImportacao != Constantes.StatusImportLote.FINALIZADO);
            if (count > 0)
            {
                if (_msgLogAuditoria == null)
                {
                    _msgLogAuditoria = new LogAuditoria();
                    _msgLogAuditoria.Mensagem = string.Format("Importação de Garantia Manual! Quantidade: {0}", count);
                }

                _msgLogAuditoria.Acao = "NORISKBO: Importação em Lote";

                WRApplicationServiceHelper.SalvarLogAuditoria(_msgLogAuditoria);

                _msgLogAuditoria = null;
            }

            InvokeSalvarDadosDeImportacao();
        }
        
        private void InvokeSalvarDadosDeImportacao()
        {
            base.BusyText = "Importando Dados...";
            base.StartBusy();

            base.IsImporting = true;

            var contratos = GetDadosParaSalvar(10);

            if (contratos.Count > 0)
            {
                _service.BeginSalvarDadosDeImportacao(contratos, AppHelper.NomeUsuario,
                   (pAsyncResult) =>
                   {
                       Deployment.Current.Dispatcher.BeginInvoke(delegate()
                       {
                           try
                           {
                               var retorno = ((ServiceGarantia.IServiceGarantia)pAsyncResult.AsyncState).EndSalvarDadosDeImportacao(pAsyncResult);
                               
                               if (retorno != null && retorno.Count > 0)
                               {
                                   foreach (var item in retorno)
                                   {
                                       if (item.IdGarantia > 0)
                                           item.CodigoStatus = Constantes.StatusFluxoLM.RASCUNHO;
                                       else
                                           _erroNaImportacao = true;

                                       this.ValidarRetornoDados(item);
                                   }
                               }

                               InvokeSalvarDadosDeImportacao();

                           }
                           catch (Exception ex)
                           {
                               _erroNaImportacao = true;
                               MessageBoxHelper.ShowErroMethod(base.TitleView, "ComandoImportarDados", ex);

                               base.StopBusy();
                           }
                           finally
                           {
                               base.NotifyProperties();
                               base.EndBusy("Carregando...");

                               if (!IsBusy)
                               {
                                   //Remover todos os garantidores que foram excluidos
                                   var garantias = DadosPlanilha.Where(w => w.CodigoStatus == Constantes.StatusFluxoLM.RASCUNHO);

                                   foreach (var ig in garantias)
                                   {
                                       ig.Garantidores.RemoveAll(delegate(ServiceGarantia.GarantidorManualLote p)
                                       {
                                           return p.FlagAcaoSQL == ServiceGarantia.enumAcaoSQL.Delete;
                                       });
                                   }

                                   AtualizarListaGarantidores();

                                   if (!_erroNaImportacao)
                                   {
                                       MessageBoxHelper.ShowSucess("Importação em Lote", "Processo de Importação realizado com sucesso!");
                                   }
                                   else
                                   {
                                       MessageBoxHelper.ShowWarning("Importação em Lote", "Verifique os erros e tente novamente.");
                                       _erroNaImportacao = false;
                                   }
                               }

                           }
                       });

                   }, _service);
            }
            else
            {
                base.IsImporting = false;

                base.NotifyProperties();
                base.EndBusy("Carregando...");
            }
        }

        private List<ServiceGarantia.GarantiaManualImportacao> GetDadosParaSalvar(int pQtdItens)
        {
            var result = new List<ServiceGarantia.GarantiaManualImportacao>();

            var dados = DadosPlanilha.Where(a => a.StatusImportacao != Constantes.StatusImportLote.PROCESSANDO
                                              && a.StatusImportacao != Constantes.StatusImportLote.FINALIZADO
                                              && a.StatusImportacao != Constantes.StatusImportLote.ERRO).Take(pQtdItens);

            foreach (var item in dados)
            {
                item.StatusImportacao = Constantes.StatusImportLote.PROCESSANDO;
                result.Add(GeneralHelper.SincProperties(item, new ServiceGarantia.GarantiaManualImportacao()));
            }

            return result;
        }

        #endregion

        #endregion //métodos adicionais
    }

}
